package com.atguigu.acl.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.atguigu.acl.bo.AdminUserDetails;
import com.atguigu.acl.dto.UpdateAdminPasswordParam;
import com.atguigu.acl.entity.*;
import com.atguigu.acl.mapper.AdminMapper;
import com.atguigu.acl.mapper.AdminPermissionMapper;
import com.atguigu.acl.mapper.AdminRoleMapper;
import com.atguigu.acl.service.AdminCacheService;
import com.atguigu.acl.service.AdminService;
import com.atguigu.serurity.util.JwtTokenUtil;
import com.atguigu.utils.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 管理员表 服务实现类
 * </p>
 *
 * @author smday
 * @since 2020-08-10
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    private static final Logger log = LoggerFactory.getLogger(AdminServiceImpl.class);

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AdminCacheService adminCacheService;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Autowired
    private AdminPermissionMapper adminPermissionMapper;


    public Admin getAdminByUsername(String username) {
        //从缓存中取
        Admin admin = adminCacheService.getAdmin(username);
        if (admin == null) {
            QueryWrapper<Admin> wrapper = new QueryWrapper<>();
            wrapper.eq("username", username);

            //从数据库中取
            List<Admin> admins = baseMapper.selectList(wrapper);
            if (CollUtil.isNotEmpty(admins)) {
                admin = admins.get(0);
                adminCacheService.setAdmin(admin);
            }
        }
        return admin;
    }

    @Override
    public String refreshToken(String oldToken) {
        return jwtTokenUtil.refreshHeadToken(oldToken);
    }

    @Override
    public Admin getItem(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public Map<String, Object> list(String keyword, Integer pageSize, Integer pageNum) {

        Page<Admin> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        if (!StrUtil.isEmpty(keyword)) {
            wrapper.like("username",  keyword );
            wrapper.or().like("nick_name",  keyword );
        }
        baseMapper.selectPage(page, wrapper);
        Map<String, Object> map = PageUtils.convertPageToMap(page);

        return map;
    }

    @Override
    public int update(Long id, Admin admin) {

        admin.setId(id);
        Admin rawAdmin = baseMapper.selectById(id);
        //与原加密密码相同的不需要修改
        if (rawAdmin.getPassword().equals(admin.getPassword())) {
            admin.setPassword(null);
        } else {
            if (StrUtil.isEmpty(admin.getPassword())) {
                admin.setPassword(null);
            } else {
                admin.setPassword(passwordEncoder.encode(admin.getPassword()));
            }
        }
        int count = baseMapper.updateById(admin);
        adminCacheService.delAdmin(id);
        return count;
    }



    @Override
    public int delete(Long id) {
        adminCacheService.delAdmin(id);
        int count = baseMapper.deleteById(id);
        adminCacheService.delResourceList(id);
        return count;
    }

    @Override
    public int updateRole(Long adminId, List<Long> roleIds) {
        //先删除原先的关系
        int count = roleIds == null ? 0 : roleIds.size();

        QueryWrapper<AdminRole> wrapper = new QueryWrapper<>();
        wrapper.eq("admin_id", adminId);
        adminRoleMapper.delete(wrapper);
        AdminRole adminRole = null;
        List<AdminRole> adminRoleList = new ArrayList<>();
        if (CollUtil.isNotEmpty(roleIds)) {
            for (Long roleId : roleIds) {
                adminRole = new AdminRole();
                adminRole.setAdminId(adminId);
                adminRole.setRoleId(roleId);
                adminRoleList.add(adminRole);
            }
            adminRoleMapper.insertList(adminRoleList);
        }
        //清除资源缓存
        adminCacheService.delResourceList(adminId);
        return count;
    }

    @Override
    public List<Role> getRoleList(Long adminId) {
        return adminRoleMapper.getRoleList(adminId);
    }

    @Override
    public String login(String username, String password) {
        String token = null;
        try {
            UserDetails userDetails = loadUserByUsername(username);
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                throw new BadCredentialsException("密码错误");
            }
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities()
            );
            SecurityContextHolder.getContext().setAuthentication(auth);
            token = jwtTokenUtil.generateToken(userDetails);
            //记录日志
            //insertLoginLog(username);
        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
        }

        return token;

    }


    public UserDetails loadUserByUsername(String username) {
        //获取用户信息
        Admin admin = getAdminByUsername(username);
        if (admin != null) {
            List<Resource> resourceList = getResourceList(admin.getId());
            return new AdminUserDetails(admin, resourceList);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    @Override
    public int insert(Admin admin) {

        String password = admin.getPassword();
        String encode = passwordEncoder.encode(password);
        admin.setPassword(encode);
        return baseMapper.insert(admin);

    }

    public List<Resource> getResourceList(Long adminId) {
        List<Resource> resourceList = adminCacheService.getResourceList(adminId);
        if (CollUtil.isNotEmpty(resourceList)) {
            return resourceList;
        }
        resourceList = adminRoleMapper.getResourceList(adminId);
        if (CollUtil.isNotEmpty(resourceList)) {
            adminCacheService.setResourceList(adminId, resourceList);
        }
        return resourceList;
    }

    @Override
    public int updatePermission(Long adminId, List<Long> permissionIds) {
        //删除所有的权限关系
        QueryWrapper<AdminPermission> wrapper = new QueryWrapper<>();
        wrapper.eq("admin_id", adminId);
        adminPermissionMapper.delete(wrapper);

        //获取用户所有的角色权限
        List<Permission> permissionList = adminRoleMapper.getRolePermissionList(adminId);
        //角色权限的id集合
        List<Long> rolePermissionList = permissionList.stream().map(Permission::getId).collect(Collectors.toList());

        if (CollUtil.isNotEmpty(permissionIds)) {
            List<AdminPermission> adminPermissionList = new ArrayList<>();
            //筛选+权限
            List<Long> addPermissionIdList = permissionIds.stream().
                    filter(permissionId -> !rolePermissionList.contains(permissionId))
                    .collect(Collectors.toList());
            //筛选-权限
            List<Long> subPermissionList = rolePermissionList.stream().
                    filter(permissionId -> !permissionIds.contains(permissionId))
                    .collect(Collectors.toList());
            adminPermissionList.addAll(convert(adminId, 1, addPermissionIdList));
            adminPermissionList.addAll(convert(adminId, -1, subPermissionList));

            return adminPermissionMapper.insertList(adminPermissionList);


        }

        return 0;
    }

    /**
     * 将+-权限关系转化为对象
     */
    private List<AdminPermission> convert(Long adminId, Integer type, List<Long> permissionIdList) {
        return permissionIdList.stream().map(permissionId -> {
            AdminPermission adminPermission = new AdminPermission();
            adminPermission.setAdminId(adminId);
            adminPermission.setType(type);
            adminPermission.setPermissionId(permissionId);
            return adminPermission;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Permission> getPermissionList(Long adminId) {
        return adminRoleMapper.getPermissionList(adminId);
    }

    @Override
    public int updatePassword(UpdateAdminPasswordParam updatePasswordParam) {
        return 0;
    }


}
